# pragma once

# include "cpp_tools_Headers.h"

namespace cpp_tools
{
    Eigen::VectorXd gradient(const Eigen::VectorXd& f) 
    {
        int n = f.size();
        Eigen::VectorXd grad = Eigen::VectorXd::Zero(n);

        // 中心差分
        for (int i = 1; i < n - 1; ++i) {
            grad(i) = 0.5 * (f(i + 1) - f(i - 1));
        }

        // 边界处理
        grad(0) = f(1) - f(0);
        grad(n - 1) = f(n - 1) - f(n - 2);

        return grad;
    }

    Eigen::VectorXd gradient(const Eigen::VectorXd &f, const Eigen::VectorXd &x) 
    {
        int n = f.size();
        Eigen::VectorXd grad = Eigen::VectorXd::Zero(n);

        // 中心差分
        for (int i = 1; i < n - 1; ++i) {
            grad(i) = (f(i + 1) - f(i - 1)) / (x(i + 1) - x(i - 1));
        }

        // 边界处理
        grad(0) = (f(1) - f(0)) / (x(1) - x(0));
        grad(n - 1) = (f(n - 1) - f(n - 2)) / (x(n - 1) - x(n - 2));

        return grad;
    }
} // namespace cpp_tools
